<!DOCTYPE html>
<html lang='en'><head>
  <title>F u n c t o o l s的新功能 | 江小凡的博客</title>
  <meta charset='utf-8'>
  <meta name="generator" content="Hugo 0.76.5" />
  <meta name = 'viewport' content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'>
  <meta http-equiv = 'X-UA-Compatible' content = 'IE=edge'>
<meta property = 'og:locale' content = 'en_US' />
<meta property="og:type" content="article">
<meta property = 'og:title' content = 'FUNCTOOLS的新功能' />
<meta name="description" content="functools - 可调用对象的高阶函数和操作
functools模块用于高阶函数：作用于或返回其他函数的函数。一般来说，对于这个模块，任何可调用对象都可以被视为函数。在实际开发中,经常用到,比如lru_cache以及partial.">
<meta property = 'og:description' content = 'functools - 可调用对象的高阶函数和操作
functools模块用于高阶函数：作用于或返回其他函数的函数。一般来说，对于这个模块，任何可调用对象都可以被视为函数。在实际开发中,经常用到,比如lru_cache以及partial.'>
<meta property = 'og:url' content = 'https://jxiaof.com/post/function_tools/' />
<meta property = 'og:image' content = 'https://jxiaof.com/images/frustrated.jpg'/>
<meta name = 'twitter:card' content = 'summary_large_image' />
<meta name = 'twitter:creator' content = ''>
<meta name = 'twitter:title' content = 'FUNCTOOLS的新功能' />
<meta property = 'twitter:description'  content = 'functools - 可调用对象的高阶函数和操作
functools模块用于高阶函数：作用于或返回其他函数的函数。一般来说，对于这个模块，任何可调用对象都可以被视为函数。在实际开发中,经常用到,比如lru_cache以及partial.'/>
<meta name = 'twitter:image' content = 'https://jxiaof.com/images/frustrated.jpg' />
<link rel='apple-touch-icon' sizes='180x180' href='https://jxiaof.com/images/icons/apple-touch-icon.png'>
<link rel='icon' type='image/png' sizes='32x32' href='https://jxiaof.com/images/icons/favicon-32x32.png'>
<link rel='icon' type='image/png' sizes='16x16' href='https://jxiaof.com/images/icons/favicon-16x16.png'>
<link rel='manifest' href='https://jxiaof.com/images/icons/site.webmanifest'>

  <link rel='canonical' href='https://jxiaof.com/post/function_tools/'>
  <link rel = 'stylesheet' href = 'https://jxiaof.com/css/styles.b934c9412cc837b60543673c5f879b59569b1c7bea59b56896858a3b0a15220c8dbd91e80317b591a1857e31aa26b3bf8fbaca17c5bab12ff1231a272cd6bd6d.css' integrity = 'sha512-uTTJQSzIN7YFQ2c8X4ebWVabHHvqWbVoloWKOwoVIgyNvZHoAxe1kaGFfjGqJrO/j7rKF8W6sS/xIxonLNa9bQ=='>
</head>

  <body><div class = 'nav-drop'>
  <div class = 'nav-body'>
      <a href = 'https://jxiaof.com/about/' class = 'nav_item'>About</a>
    <div class = 'nav-close'></div>
  </div>
</div><header class = 'nav' >
  <nav class = 'nav-menu'>
    <a href='https://jxiaof.com/' class = 'nav-brand nav_item'>江小凡的博客</a>
    <div class = 'nav_bar-wrap'>
      <div class = 'nav_bar'></div>
    </div>
  </nav>
</header>


    <main>
<section class = 'post_header' style = 'background-image:url(https://jxiaof.com/images/frustrated.jpg);'>
  <h1 class='post_title'>FUNCTOOLS的新功能</h1>
</section>
<div class = 'post'>
  <article class='post_content'><p><strong>functools - 可调用对象的高阶函数和操作</strong></p>
<p>functools模块用于高阶函数：作用于或返回其他函数的函数。一般来说，对于这个模块，任何可调用对象都可以被视为函数。在实际开发中,经常用到,比如lru_cache以及partial.</p>
<p>functools 模块定义了以下函数︰</p>
<p><strong>functools.cmp_to_key(func)</strong>
将旧风格的比较函数转换为key函数。用于接受key函数的工具（例如sorted()，min()，max()，heapq.nlargest ），heapq.nsmallest()，itertools.groupby()）。此函数主要用作从支持使用比较函数的Python 2转换的程序的过渡工具。</p>
<p>比较函数是任何一个可调用的函数，且包含两个参数，对参数进行比较，如果小于返回负数，等于返回0，大于返回正数。Key函数是一个可调用对象，它接受一个参数并返回另一个值作为排序的键。</p>
<p>示例：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python">sorted(iterable, key<span style="color:#f92672">=</span>cmp_to_key(locale<span style="color:#f92672">.</span>strcoll))  <span style="color:#75715e"># locale-aware sort order</span>
</code></pre></div><p>版本3.2中的新功能。</p>
<p><strong>@functools.lru_cache(maxsize=128, typed=False)</strong>
装饰器用一个memoizing可调用函数来包装一个函数，它可以保存最近的maxsize个调用。当使用相同的参数定期调用昂贵的或I / O绑定的函数时，可以节省时间。</p>
<p>由于字典用于缓存结果，函数的位置和关键字参数必须是可哈希的。</p>
<p>如果maxsize设置为None，则禁用LRU功能，并且缓存可以无限制增长。当maxsize是二的幂时，LRU功能执行得最好。</p>
<p>如果类型设置为True，则不同类型的函数参数将单独缓存。例如，f(3)和f(3.0)将被视为具有不同结果的不同调用。</p>
<p>To help measure the effectiveness of the cache and tune the maxsize parameter, the wrapped function is instrumented with a cache_info() function that returns a named tuple showing hits, misses, maxsize and currsize. 在多线程环境中，命中和未命中是近似的。</p>
<p>装饰器还提供了用于清除或使缓存无效的cache_clear()函数。</p>
<p>原始的底层函数可以通过__wrapped__属性访问。这对于内省，绕过缓存或者用不同的缓存重新封装函数很有用。</p>
<p>当最近的呼叫是即将来电的最佳预测因子时，LRU（最近最少使用）高速缓存效果最好（例如，新闻服务器上最受欢迎的文章往往每天都更改）。缓存的大小限制确保缓存不会在长时间运行的进程（如Web服务器）上不受限制地增长。</p>
<p>用于静态Web内容的LRU缓存示例：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#a6e22e">@lru_cache</span>(maxsize<span style="color:#f92672">=</span><span style="color:#ae81ff">32</span>)
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_pep</span>(num):
    <span style="color:#e6db74">&#39;Retrieve text of a Python Enhancement Proposal&#39;</span>
    resource <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;http://www.python.org/dev/peps/pep-</span><span style="color:#e6db74">%04d</span><span style="color:#e6db74">/&#39;</span> <span style="color:#f92672">%</span> num
    <span style="color:#66d9ef">try</span>:
        <span style="color:#66d9ef">with</span> urllib<span style="color:#f92672">.</span>request<span style="color:#f92672">.</span>urlopen(resource) <span style="color:#66d9ef">as</span> s:
            <span style="color:#66d9ef">return</span> s<span style="color:#f92672">.</span>read()
    <span style="color:#66d9ef">except</span> urllib<span style="color:#f92672">.</span>error<span style="color:#f92672">.</span>HTTPError:
        <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#39;Not Found&#39;</span>

<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#66d9ef">for</span> n <span style="color:#f92672">in</span> <span style="color:#ae81ff">8</span>, <span style="color:#ae81ff">290</span>, <span style="color:#ae81ff">308</span>, <span style="color:#ae81ff">320</span>, <span style="color:#ae81ff">8</span>, <span style="color:#ae81ff">218</span>, <span style="color:#ae81ff">320</span>, <span style="color:#ae81ff">279</span>, <span style="color:#ae81ff">289</span>, <span style="color:#ae81ff">320</span>, <span style="color:#ae81ff">9991</span>:
<span style="color:#f92672">&gt;&gt;&gt;</span>      pep <span style="color:#f92672">=</span> get_pep(n)
<span style="color:#f92672">&gt;&gt;&gt;</span>      <span style="color:#66d9ef">print</span>(n, len(pep))

<span style="color:#f92672">&gt;&gt;&gt;</span> get_pep<span style="color:#f92672">.</span>cache_info()
<span style="color:#f92672">&gt;&gt;&gt;</span> CacheInfo(hits<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span>, misses<span style="color:#f92672">=</span><span style="color:#ae81ff">8</span>, maxsize<span style="color:#f92672">=</span><span style="color:#ae81ff">32</span>, currsize<span style="color:#f92672">=</span><span style="color:#ae81ff">8</span>)
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#960050;background-color:#1e0010">使用高速缓存实现动态规划技术有效计算斐波纳契数的示例：</span>

<span style="color:#a6e22e">@lru_cache</span>(maxsize<span style="color:#f92672">=</span>None)
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">fib</span>(n):
    <span style="color:#66d9ef">if</span> n <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">2</span>:
        <span style="color:#66d9ef">return</span> n
    <span style="color:#66d9ef">return</span> fib(n<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>) <span style="color:#f92672">+</span> fib(n<span style="color:#f92672">-</span><span style="color:#ae81ff">2</span>)

<span style="color:#f92672">&gt;&gt;&gt;</span> [fib(n) <span style="color:#66d9ef">for</span> n <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">16</span>)]
<span style="color:#f92672">&gt;&gt;&gt;</span> [<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">3</span>, <span style="color:#ae81ff">5</span>, <span style="color:#ae81ff">8</span>, <span style="color:#ae81ff">13</span>, <span style="color:#ae81ff">21</span>, <span style="color:#ae81ff">34</span>, <span style="color:#ae81ff">55</span>, <span style="color:#ae81ff">89</span>, <span style="color:#ae81ff">144</span>, <span style="color:#ae81ff">233</span>, <span style="color:#ae81ff">377</span>, <span style="color:#ae81ff">610</span>]

<span style="color:#f92672">&gt;&gt;&gt;</span> fib<span style="color:#f92672">.</span>cache_info()
<span style="color:#f92672">&gt;&gt;&gt;</span> CacheInfo(hits<span style="color:#f92672">=</span><span style="color:#ae81ff">28</span>, misses<span style="color:#f92672">=</span><span style="color:#ae81ff">16</span>, maxsize<span style="color:#f92672">=</span>None, currsize<span style="color:#f92672">=</span><span style="color:#ae81ff">16</span>)
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#960050;background-color:#1e0010">版本</span><span style="color:#ae81ff">3.2</span><span style="color:#960050;background-color:#1e0010">中的新功能。</span>
</code></pre></div><p>在版本3.3中更改：添加了类型选项。</p>
<p><strong>@functools.total_ordering</strong>
给定一个定义了一个或多个富比较排序方法的类，该方法提供了一个类装饰器。这简化了指定所有可能的富比较操作的工作量。</p>
<p>类必须定义__lt__()，__le__()，__gt__()或__ge__()此外，该类应提供一个__eq__()方法。</p>
<p>示例：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#a6e22e">@total_ordering</span>
<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Student</span>:
    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">_is_valid_operand</span>(self, other):
        <span style="color:#66d9ef">return</span> (hasattr(other, <span style="color:#e6db74">&#34;lastname&#34;</span>) <span style="color:#f92672">and</span>
                hasattr(other, <span style="color:#e6db74">&#34;firstname&#34;</span>))
    <span style="color:#66d9ef">def</span> __eq__(self, other):
        <span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> self<span style="color:#f92672">.</span>_is_valid_operand(other):
            <span style="color:#66d9ef">return</span> NotImplemented
        <span style="color:#66d9ef">return</span> ((self<span style="color:#f92672">.</span>lastname<span style="color:#f92672">.</span>lower(), self<span style="color:#f92672">.</span>firstname<span style="color:#f92672">.</span>lower()) <span style="color:#f92672">==</span>
                (other<span style="color:#f92672">.</span>lastname<span style="color:#f92672">.</span>lower(), other<span style="color:#f92672">.</span>firstname<span style="color:#f92672">.</span>lower()))
    <span style="color:#66d9ef">def</span> __lt__(self, other):
        <span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> self<span style="color:#f92672">.</span>_is_valid_operand(other):
            <span style="color:#66d9ef">return</span> NotImplemented
        <span style="color:#66d9ef">return</span> ((self<span style="color:#f92672">.</span>lastname<span style="color:#f92672">.</span>lower(), self<span style="color:#f92672">.</span>firstname<span style="color:#f92672">.</span>lower()) <span style="color:#f92672">&lt;</span>
                (other<span style="color:#f92672">.</span>lastname<span style="color:#f92672">.</span>lower(), other<span style="color:#f92672">.</span>firstname<span style="color:#f92672">.</span>lower()))
</code></pre></div><p>注意</p>
<p>虽然这个装饰器使得容易创建行为良好的完全有序类型，但是以导致比较方法的较慢执行和更复杂的堆栈跟踪为代价的。如果性能基准测试表明这是给定应用程序的瓶颈，则实施所有六种丰富的比较方法可能提供一个容易的速度提升。</p>
<p>版本3.2中的新功能。</p>
<p>在版本3.4中更改：现在支持从无法识别的类型的基础比较函数返回未实现。</p>
<p><strong>functools.partial(func, *args, **keywords)</strong>
返回一个新的partial对象，该对象在调用时的行为将类似采用位置参数args和关键字参数keywords对func的调用。如果提供多个参数调用， 它们会被追加给 args。如果提供额外的关键字参数， 它们会扩展和覆盖 keywords。大致相当于：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">partial</span>(func, <span style="color:#f92672">*</span>args, <span style="color:#f92672">**</span>keywords):
    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">newfunc</span>(<span style="color:#f92672">*</span>fargs, <span style="color:#f92672">**</span>fkeywords):
        newkeywords <span style="color:#f92672">=</span> keywords<span style="color:#f92672">.</span>copy()
        newkeywords<span style="color:#f92672">.</span>update(fkeywords)
        <span style="color:#66d9ef">return</span> func(<span style="color:#f92672">*</span>args, <span style="color:#f92672">*</span>fargs, <span style="color:#f92672">**</span>newkeywords)
    newfunc<span style="color:#f92672">.</span>func <span style="color:#f92672">=</span> func
    newfunc<span style="color:#f92672">.</span>args <span style="color:#f92672">=</span> args
    newfunc<span style="color:#f92672">.</span>keywords <span style="color:#f92672">=</span> keywords
    <span style="color:#66d9ef">return</span> newfunc
</code></pre></div><p>partial()用于部分函数应用程序，其“冻结”函数的参数和/或关键字的某些部分，从而产生具有简化声明的新对象。例如，partial()可用于创建一个可调用对象，其行为类似于int()函数但base参数默认为2：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">from</span> functools <span style="color:#f92672">import</span> partial
basetwo <span style="color:#f92672">=</span> partial(int, base<span style="color:#f92672">=</span><span style="color:#ae81ff">2</span>)
basetwo<span style="color:#f92672">.</span>__doc__ <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;Convert base 2 string to an int.&#39;</span>
basetwo(<span style="color:#e6db74">&#39;10010&#39;</span>)
<span style="color:#ae81ff">18</span>
</code></pre></div><p><strong>class functools.partialmethod(func, *args, **keywords)</strong>
返回一个新的partialmethod描述器，它的行为类似于partial，除了它被设计为用作方法定义而不是直接可调用。</p>
<p>func必须是descriptor或可调用对象（这两个对象都像常规函数一样被处理为描述器）。</p>
<p>When func is a descriptor (such as a normal Python function, classmethod(), staticmethod(), abstractmethod() or another instance of partialmethod), calls to <strong>get</strong> are delegated to the underlying descriptor, and an appropriate partial object returned as the result.</p>
<p>当func是非描述符可调用时，将动态创建适当的绑定方法。在作为方法使用时，它的行为类似于普通的Python函数：self参数将被插入作为第一个位置参数，甚至在args和t2&gt;提供给partialmethod构造函数。</p>
<p>示例：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Cell</span>(object):
     <span style="color:#66d9ef">def</span> __init__(self):
         self<span style="color:#f92672">.</span>_alive <span style="color:#f92672">=</span> False
     <span style="color:#a6e22e">@property</span>
     <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">alive</span>(self):
         <span style="color:#66d9ef">return</span> self<span style="color:#f92672">.</span>_alive
     <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">set_state</span>(self, state):
         self<span style="color:#f92672">.</span>_alive <span style="color:#f92672">=</span> bool(state)
     set_alive <span style="color:#f92672">=</span> partialmethod(set_state, True)
     set_dead <span style="color:#f92672">=</span> partialmethod(set_state, False)

c <span style="color:#f92672">=</span> Cell()
c<span style="color:#f92672">.</span>alive
False
c<span style="color:#f92672">.</span>set_alive()
c<span style="color:#f92672">.</span>alive
True
<span style="color:#960050;background-color:#1e0010">版本</span><span style="color:#ae81ff">3.4</span><span style="color:#960050;background-color:#1e0010">中的新功能。</span>
</code></pre></div><p><strong>functools.reduce(function, iterable[, initializer])</strong>
将带有两个参数的 function 从左到右累积应用到 sequence 的元素中，以将该序列规约为单个值。例如，reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) 计算 ((((1+2)+3)+4)+5)。左参数 x 是累积值，右参数 y 是来自 sequence 的更新值。如果存在可选的 initializer，则它将放置在计算序列的元素之前，并在序列为空时用作默认值。如果未提供 initializer 且 sequence 只包含一个元素，则返回第一个元素。</p>
<p>大致相当于：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">reduce</span>(function, iterable, initializer<span style="color:#f92672">=</span>None):
    it <span style="color:#f92672">=</span> iter(iterable)
    <span style="color:#66d9ef">if</span> initializer <span style="color:#f92672">is</span> None:
        value <span style="color:#f92672">=</span> next(it)
    <span style="color:#66d9ef">else</span>:
        value <span style="color:#f92672">=</span> initializer
    <span style="color:#66d9ef">for</span> element <span style="color:#f92672">in</span> it:
        value <span style="color:#f92672">=</span> function(value, element)
    <span style="color:#66d9ef">return</span> value
</code></pre></div><p><strong>@functools.singledispatch(default)</strong>
将函数转换为single-dispatch generic function。</p>
<p>要定义通用函数，请使用@singledispatch装饰器进行装饰。注意，分派发生在第一个参数的类型上，相应地创建你的函数：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#f92672">from</span> functools <span style="color:#f92672">import</span> singledispatch
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#a6e22e">@singledispatch</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">fun</span>(arg, verbose<span style="color:#f92672">=</span>False):
<span style="color:#f92672">&gt;&gt;&gt;</span>      <span style="color:#66d9ef">if</span> verbose:
<span style="color:#f92672">&gt;&gt;&gt;</span>          <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#34;Let me just say,&#34;</span>, end<span style="color:#f92672">=</span><span style="color:#e6db74">&#34; &#34;</span>)
<span style="color:#f92672">&gt;&gt;&gt;</span>      <span style="color:#66d9ef">print</span>(arg)
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#960050;background-color:#1e0010">要向函数添加重载的实现，请使用通用函数的</span>register()<span style="color:#960050;background-color:#1e0010">属性。它是一个装饰器，接受一个类型参数和装饰实现该类型的操作的函数：</span>

<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#a6e22e">@fun.register</span>(int)
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">_</span>(arg, verbose<span style="color:#f92672">=</span>False):
<span style="color:#f92672">&gt;&gt;&gt;</span>      <span style="color:#66d9ef">if</span> verbose:
<span style="color:#f92672">&gt;&gt;&gt;</span>          <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#34;Strength in numbers, eh?&#34;</span>, end<span style="color:#f92672">=</span><span style="color:#e6db74">&#34; &#34;</span>)
<span style="color:#f92672">&gt;&gt;&gt;</span>      <span style="color:#66d9ef">print</span>(arg)
<span style="color:#f92672">&gt;&gt;&gt;</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#a6e22e">@fun.register</span>(list)
<span style="color:#f92672">&gt;&gt;&gt;</span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">_</span>(arg, verbose<span style="color:#f92672">=</span>False):
<span style="color:#f92672">&gt;&gt;&gt;</span>      <span style="color:#66d9ef">if</span> verbose:
<span style="color:#f92672">&gt;&gt;&gt;</span>          <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#34;Enumerate this:&#34;</span>)
<span style="color:#f92672">&gt;&gt;&gt;</span>      <span style="color:#66d9ef">for</span> i, elem <span style="color:#f92672">in</span> enumerate(arg):
<span style="color:#f92672">&gt;&gt;&gt;</span>          <span style="color:#66d9ef">print</span>(i, elem)
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#960050;background-color:#1e0010">要启用注册</span>lambda和预先存在的函数<span style="color:#960050;background-color:#1e0010">，可以以函数形式使用</span>register()<span style="color:#960050;background-color:#1e0010">属性：</span>

<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">nothing</span>(arg, verbose<span style="color:#f92672">=</span>False):
<span style="color:#f92672">&gt;&gt;&gt;</span>      <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#34;Nothing.&#34;</span>)
<span style="color:#f92672">&gt;&gt;&gt;</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> fun<span style="color:#f92672">.</span>register(type(None), nothing)
<span style="color:#f92672">&gt;&gt;&gt;</span> register()<span style="color:#960050;background-color:#1e0010">属性返回未装饰函数（原函数），该函数使装饰器堆叠，</span>pickle化<span style="color:#960050;background-color:#1e0010">（序列化）以及为每个变体独立创建单元测试：</span>

<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#a6e22e">@fun.register</span>(float)
<span style="color:#f92672">&gt;&gt;&gt;</span>  <span style="color:#a6e22e">@fun.register</span>(Decimal)
<span style="color:#f92672">&gt;&gt;&gt;</span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">fun_num</span>(arg, verbose<span style="color:#f92672">=</span>False):
<span style="color:#f92672">&gt;&gt;&gt;</span>      <span style="color:#66d9ef">if</span> verbose:
<span style="color:#f92672">&gt;&gt;&gt;</span>          <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#34;Half of your number:&#34;</span>, end<span style="color:#f92672">=</span><span style="color:#e6db74">&#34; &#34;</span>)
<span style="color:#f92672">&gt;&gt;&gt;</span>      <span style="color:#66d9ef">print</span>(arg <span style="color:#f92672">/</span> <span style="color:#ae81ff">2</span>)
<span style="color:#f92672">&gt;&gt;&gt;</span> 
<span style="color:#f92672">&gt;&gt;&gt;</span> fun_num <span style="color:#f92672">is</span> fun
<span style="color:#f92672">&gt;&gt;&gt;</span> False
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#960050;background-color:#1e0010">当被调用时，泛型函数调度第一个参数的类型：</span>

<span style="color:#f92672">&gt;&gt;&gt;</span> fun(<span style="color:#e6db74">&#34;Hello, world.&#34;</span>)
<span style="color:#f92672">&gt;&gt;&gt;</span> Hello, world<span style="color:#f92672">.</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> fun(<span style="color:#e6db74">&#34;test.&#34;</span>, verbose<span style="color:#f92672">=</span>True)
<span style="color:#f92672">&gt;&gt;&gt;</span> Let me just say, test<span style="color:#f92672">.</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> fun(<span style="color:#ae81ff">42</span>, verbose<span style="color:#f92672">=</span>True)
<span style="color:#f92672">&gt;&gt;&gt;</span> Strength <span style="color:#f92672">in</span> numbers, eh<span style="color:#960050;background-color:#1e0010">?</span> <span style="color:#ae81ff">42</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> fun([<span style="color:#e6db74">&#39;spam&#39;</span>, <span style="color:#e6db74">&#39;spam&#39;</span>, <span style="color:#e6db74">&#39;eggs&#39;</span>, <span style="color:#e6db74">&#39;spam&#39;</span>], verbose<span style="color:#f92672">=</span>True)
<span style="color:#f92672">&gt;&gt;&gt;</span> Enumerate this:
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#ae81ff">0</span> spam
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#ae81ff">1</span> spam
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#ae81ff">2</span> eggs
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#ae81ff">3</span> spam
<span style="color:#f92672">&gt;&gt;&gt;</span> fun(None)
<span style="color:#f92672">&gt;&gt;&gt;</span> Nothing<span style="color:#f92672">.</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> fun(<span style="color:#ae81ff">1.23</span>)
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#ae81ff">0.615</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#960050;background-color:#1e0010">在没有针对特定类型的注册实现的情况下，其方法解析顺序用于找到更通用的实现。用</span><span style="color:#a6e22e">@singledispatch装饰的原始函数是为基础object类型注册的</span><span style="color:#960050;background-color:#1e0010">，这意味着如果没有找到更好的实现，则使用它。</span>
</code></pre></div><p>要检查通用函数为给定类型选择的实现，请使用dispatch()属性：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">&gt;&gt;&gt;</span> fun<span style="color:#f92672">.</span>dispatch(float)
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#f92672">&lt;</span>function fun_num at <span style="color:#ae81ff">0x1035a2840</span><span style="color:#f92672">&gt;</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> fun<span style="color:#f92672">.</span>dispatch(dict)    <span style="color:#75715e"># note: default implementation</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#f92672">&lt;</span>function fun at <span style="color:#ae81ff">0x103fe0000</span><span style="color:#f92672">&gt;</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#960050;background-color:#1e0010">要访问所有注册的实现，请使用只读</span>registry属性<span style="color:#960050;background-color:#1e0010">：</span>

<span style="color:#f92672">&gt;&gt;&gt;</span> fun<span style="color:#f92672">.</span>registry<span style="color:#f92672">.</span>keys()
<span style="color:#f92672">&gt;&gt;&gt;</span> dict_keys([<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">class</span> <span style="color:#960050;background-color:#1e0010">&#39;</span><span style="color:#a6e22e">NoneType</span><span style="color:#e6db74">&#39;&gt;, &lt;class &#39;</span>int<span style="color:#e6db74">&#39;&gt;, &lt;class &#39;</span>object<span style="color:#e6db74">&#39;&gt;,</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#f92672">&lt;</span><span style="color:#66d9ef">class</span> <span style="color:#960050;background-color:#1e0010">&#39;</span><span style="color:#a6e22e">decimal</span><span style="color:#f92672">.</span>Decimal<span style="color:#e6db74">&#39;&gt;, &lt;class &#39;</span>list<span style="color:#e6db74">&#39;&gt;,</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#f92672">&lt;</span><span style="color:#66d9ef">class</span> <span style="color:#960050;background-color:#1e0010">&#39;</span><span style="color:#a6e22e">float</span><span style="color:#e6db74">&#39;&gt;])</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> fun<span style="color:#f92672">.</span>registry[float]
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#f92672">&lt;</span>function fun_num at <span style="color:#ae81ff">0x1035a2840</span><span style="color:#f92672">&gt;</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> fun<span style="color:#f92672">.</span>registry[object]
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#f92672">&lt;</span>function fun at <span style="color:#ae81ff">0x103fe0000</span><span style="color:#f92672">&gt;</span>
<span style="color:#f92672">&gt;&gt;&gt;</span> <span style="color:#960050;background-color:#1e0010">版本</span><span style="color:#ae81ff">3.4</span><span style="color:#960050;background-color:#1e0010">中的新功能。</span>
</code></pre></div><p><strong>functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)</strong>
更新一个 wrapper 函数让其更像一个 wrapped 函数。可选的参数是一个元祖，来指定原函数哪些属性被直接分配给装饰器中的匹配属性 ，哪些装饰器属性使用来自原函数的相应属性来更新。The default values for these arguments are the module level constants WRAPPER_ASSIGNMENTS (which assigns to the wrapper function’s <strong>module</strong>, <strong>name</strong>, <strong>qualname</strong>, <strong>annotations</strong> and <strong>doc</strong>, the documentation string) and WRAPPER_UPDATES (which updates the wrapper function’s <strong>dict</strong>, i.e. 实例的字典).</p>
<p>为了允许访问原始功能以进行内省和其他目的（例如，绕过缓存装饰器（例如lru_cache()），此函数会自动向包装器添加一个__wrapped__属性，该属性引用要包装的函数。</p>
<p>此函数的主要用途是在decorator函数中，它包装修饰的函数并返回包装器。如果不更新包装器函数，返回的函数的元数据将反射包装器的定义，而不是原函数的定义 ，这通常是没有意义的。</p>
<p>update_wrapper()可以与除函数之外的可调用项一起使用。忽略分配的或更新中指定的任何属性，这些属性从正在包装的对象中丢失。此函数不会尝试在包装函数中设置它们）。如果包装函数本身缺少在更新的中命名的任何属性，则仍会引发AttributeError。</p>
<p>版本3.2中的新功能：自动添加__wrapped__属性。</p>
<p>版本3.2中的新功能：默认情况下复制__annotations__属性。</p>
<p>在版本3.2中更改：缺少的属性不再触发AttributeError。</p>
<p>在版本3.4中更改： __wrapped__属性现在总是引用wrapped函数，即使该函数定义了__wrapped__属性。（参见问题17482）</p>
<p><strong>@functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)</strong>
这是一个方便的函数，用于在定义包装器函数时调用update_wrapper()作为函数装饰器。它等效于partial（update_wrapper， wrapped = wrapped， assigned = assigned， updated = updated） t4 &gt;。示例：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">from</span> functools <span style="color:#f92672">import</span> wraps
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">my_decorator</span>(f):
     <span style="color:#a6e22e">@wraps</span>(f)
     <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">wrapper</span>(<span style="color:#f92672">*</span>args, <span style="color:#f92672">**</span>kwds):
         <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#39;Calling decorated function&#39;</span>)
         <span style="color:#66d9ef">return</span> f(<span style="color:#f92672">*</span>args, <span style="color:#f92672">**</span>kwds)
     <span style="color:#66d9ef">return</span> wrapper

<span style="color:#a6e22e">@my_decorator</span>
 <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">example</span>():
     <span style="color:#e6db74">&#34;&#34;&#34;Docstring&#34;&#34;&#34;</span>
     <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#39;Called example function&#39;</span>)

example()
Calling decorated function
Called example function
example<span style="color:#f92672">.</span>__name__
<span style="color:#e6db74">&#39;example&#39;</span>
example<span style="color:#f92672">.</span>__doc__
<span style="color:#e6db74">&#39;Docstring&#39;</span>
<span style="color:#960050;background-color:#1e0010">没有使用这个装饰器工厂，示例函数的名称将是</span><span style="color:#e6db74">&#39;wrapper&#39;</span><span style="color:#960050;background-color:#1e0010">，原始</span>example()<span style="color:#960050;background-color:#1e0010">的</span>docstring将丢失<span style="color:#960050;background-color:#1e0010">。</span>
</code></pre></div><p><strong>partial对象</strong>
partial对象是由partial()创建的可调用对象。它们有三个只读属性：</p>
<p><strong>partial.func</strong>
一个可调用对象或函数。对partial对象的调用将使用新的参数和关键字转发到func。</p>
<p><strong>partial.args</strong>
最左边的位置参数将被提供给提供给partial对象调用的位置参数。</p>
<p><strong>partial.keywords</strong>
当调用partial对象时将提供的关键字参数。</p>
<p>partial对象类似于function对象，因为它们是可调用的，弱引用的，并且可以具有属性。它们有一些重要的区别。对于实例，不会自动创建__name__和__doc__属性。此外，在类中定义的partial对象的行为类似于静态方法，并且在实例属性查找期间不会转换为绑定的方法。</p>
<hr>
    <div class = 'post_extra'><div class = 'copy' data-share = 'Share Story' data-copied = 'Link Copied'>
  <svg>
    <use xlink:href="#copy"></use>
  </svg>  
</div>

    </div>

  </article>
  <div class="post-comment">
       
       <h3>Comments welcome !</h3>



<div id="vcomments"></div>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src='//unpkg.com/valine/dist/Valine.min.js'></script>
 <script type="text/javascript">
   new Valine({
       el: '#vcomments' ,
       appId: 'xb5Xl8O60fXEK4d13KsazkkL-gzGzoHsz',
       appKey: 'qyztiJ2tgf6AhvsrH088N29o',
       notify: 'false', 
       verify: 'false', 
       avatar:'mm', 
       placeholder: '说说你的看法吧...',
       visitor: 'true'
   });
 </script>
  </div>
  <aside><h3></h3>
<ul class='posts aside'>
<li class = 'post_item'>
  <a class = 'post_card' href='https://jxiaof.com/post/first/' title = 'ABOUT MYSELF' style = 'background-image: url(https://jxiaof.com/images/speakers.jpg);'>
  </a>
  <div class = 'excerpt'>
    <div class = 'excerpt_meta'><div class = 'copy' data-share = 'Share Story' data-copied = 'Link Copied'>
  <svg>
    <use xlink:href="#copy"></use>
  </svg>  
</div>

    </div>
    <h3 class = 'post_link'>
      <a href='https://jxiaof.com/post/first/'>ABOUT MYSELF</a>
    </h3>
    <p class = 'pale'><p>​        I am a light game enthusiast with poor gastrointestinal function. I go to bed …</p></p>
  </div>
</li>

<li class = 'post_item'>
  <a class = 'post_card' href='https://jxiaof.com/post/leetcode/' title = 'Leetcode' style = 'background-image: url(https://jxiaof.com/images/programmer.png);'>
  </a>
  <div class = 'excerpt'>
    <div class = 'excerpt_meta'><div class = 'copy' data-share = 'Share Story' data-copied = 'Link Copied'>
  <svg>
    <use xlink:href="#copy"></use>
  </svg>  
</div>

    </div>
    <h3 class = 'post_link'>
      <a href='https://jxiaof.com/post/leetcode/'>Leetcode</a>
    </h3>
    <p class = 'pale'>买卖股票简答:
class Solution: def maxProfit(self, prices): &#34;&#34;&#34; :type prices: …</p>
  </div>
</li>

</ul>

  </aside>
</div>
<script src = 'https://jxiaof.com/js/autosize.min.js'></script>
<script src = 'https://jxiaof.com/js/timeago.js'></script>
    </main><svg width="0" height="0" class="hidden">
  <symbol viewBox="0 0 699.428 699.428" xmlns="http://www.w3.org/2000/svg" id="copy">
    <path d="M502.714 0H240.428C194.178 0 153 42.425 153 87.429l-25.267.59c-46.228 0-84.019 41.834-84.019 86.838V612c0 45.004 41.179 87.428 87.429 87.428H459c46.249 0 87.428-42.424 87.428-87.428h21.857c46.25 0 87.429-42.424 87.429-87.428v-349.19zM459 655.715H131.143c-22.95 0-43.714-21.441-43.714-43.715V174.857c0-22.272 18.688-42.993 41.638-42.993l23.933-.721v393.429C153 569.576 194.178 612 240.428 612h262.286c0 22.273-20.765 43.715-43.714 43.715zm153-131.143c0 22.271-20.765 43.713-43.715 43.713H240.428c-22.95 0-43.714-21.441-43.714-43.713V87.429c0-22.272 20.764-43.714 43.714-43.714H459c-.351 50.337 0 87.975 0 87.975 0 45.419 40.872 86.882 87.428 86.882H612zm-65.572-349.715c-23.277 0-43.714-42.293-43.714-64.981V44.348L612 174.857zm-43.714 131.537H306c-12.065 0-21.857 9.77-21.857 21.835s9.792 21.835 21.857 21.835h196.714c12.065 0 21.857-9.771 21.857-21.835 0-12.065-9.792-21.835-21.857-21.835zm0 109.176H306c-12.065 0-21.857 9.77-21.857 21.834 0 12.066 9.792 21.836 21.857 21.836h196.714c12.065 0 21.857-9.77 21.857-21.836 0-12.064-9.792-21.834-21.857-21.834z"
    ></path>
  </symbol>
  <symbol viewBox="0 0 60.015 60.015" xmlns="http://www.w3.org/2000/svg" id="reply">
    <path d="M42.007 0h-24c-9.925 0-18 8.075-18 18v14c0 9.59 7.538 17.452 17 17.973v8.344a1.694 1.694 0 0 0 1.699 1.698c.44 0 .873-.173 1.198-.498l1.876-1.876C26.708 52.713 33.259 50 40.227 50h1.78c9.925 0 18-8.075 18-18V18c0-9.925-8.075-18-18-18zm16 32c0 8.822-7.178 16-16 16h-1.78c-7.502 0-14.556 2.921-19.86 8.226l-1.359 1.359V44a1 1 0 1 0-2 0v3.949c-8.356-.52-15-7.465-15-15.949V18c0-8.822 7.178-16 16-16h24c8.822 0 16 7.178 16 16v14z"></path>
  </symbol>
</svg>
<footer class = 'footer'>
  <div class = 'footer_inner wrap pale'>
    <p>&copy;&nbsp;<span class = 'year'></span>&nbsp;江小凡的博客.
    Designed by  <a href = 'https://www.github.com/jxiaof' title = 'Linkedin Profile'>江小凡</a></p>
  </div>
</footer>
<script src = 'https://jxiaof.com/js/index.min.c3b0a769e56310d4359f30762ab615db8cd6ce33d555ee7f68d25e8a40c63ce18bf6b273d35a9b5c033a7f6e71b1d424e74d9f542d93482215c671b3f31f885f.js'></script>

  </body>
</html>
